Competitive Nucleation Mechanism for CsPbBr3 Perovskite Nanoplatelet Growth

DOI Link: http://dx.doi.org/10.1021/acs.jpclett.0c01794

1. Loading individual images
2. Segment using ParticleSpy
3. Loading all the particles for each case
4. Plotting the results
This notebook presents the code corresponding to histograms in Figure 5

1. Loading individual images

In [1]:
import hyperspy.api as hs
import ParticleSpy.api as ps
import os
WARNING:hyperspy_gui_traitsui:The module://ipykernel.pylab.backend_inline matplotlib backend is not compatible with the traitsui GUI elements. For more information, read http://hyperspy.readthedocs.io/en/stable/user_guide/getting_started.html#possible-warnings-when-importing-hyperspy.
WARNING:hyperspy_gui_traitsui:The traitsui GUI elements are not available.
In [2]:
t75_path = r'C:\Users\eha56862\Documents\TEM for NPLs-YH-MD\T75-final'
t150_path = r'C:\Users\eha56862\Documents\TEM for NPLs-YH-MD\T150'
t200_path = r'C:\Users\eha56862\Documents\TEM for NPLs-YH-MD\T200'
In [3]:
os.listdir(t150_path)
Out[3]:
['HAADF _0002.dm3',
 'HAADF _0003.dm3',
 'HAADF _0006.dm3',
 'HAADF _0008.dm3',
 'HAADF _0010.dm3',
 'HAADF _0011.dm3',
 'HAADF _0014.dm3',
 'HAADF _0015.dm3',
 'HAADF _0016.dm3',
 'HAADF _0018.dm3',
 'HAADF _0019.dm3',
 'HAADF _0020.dm3',
 'HAADF _0155.dm3',
 'HAADF _0156.dm3',
 'HAADF _0157.dm3',
 'HAADF _0163.dm3',
 'im08.h5',
 'im10.h5',
 'im11.h5',
 'im14.h5',
 'im16.h5',
 'im19.h5']
In [4]:
os.chdir(t150_path)
t150_dm3_files = []
for file in os.listdir(t150_path):
    if file.endswith('dm3'):
        t150_dm3_files.append(file)
In [5]:
t150_dm3_files
Out[5]:
['HAADF _0002.dm3',
 'HAADF _0003.dm3',
 'HAADF _0006.dm3',
 'HAADF _0008.dm3',
 'HAADF _0010.dm3',
 'HAADF _0011.dm3',
 'HAADF _0014.dm3',
 'HAADF _0015.dm3',
 'HAADF _0016.dm3',
 'HAADF _0018.dm3',
 'HAADF _0019.dm3',
 'HAADF _0020.dm3',
 'HAADF _0155.dm3',
 'HAADF _0156.dm3',
 'HAADF _0157.dm3',
 'HAADF _0163.dm3']

2. Segment using ParticleSpy

This opens a GUI for segmentation (see instructions here). We iterate through all the images and for each case save an h5 particles file with the outcome of the segmentation.

In [31]:
n = 10
data = hs.load(t150_path + '/' + t150_dm3_files[n])
print(t150_dm3_files[n])
ps.SegUI(data)
HAADF _0019.dm3
{'threshold': 'local_otsu', 'watershed': False, 'invert': False, 'min_size': 300, 'rb_kernel': 0, 'gaussian': 2, 'local_size': 101}
Out[31]:
<ParticleSpy.SegUI.Application at 0x243e16c78b8>
In [32]:
params = ps.parameters()
params.load()
In [33]:
particles = ps.ParticleAnalysis(data, params)
In [30]:
particles.plot_area()
In [14]:
import h5py

def save_plist(p_list,filename):
    f = h5py.File(filename,'w')
    
    for i, particle in enumerate(p_list.list):
        p_group = f.create_group("Particle "+str(i))
        
        p_group.attrs["Area"] = particle.properties['area']['value']
        p_group.attrs["Area units"] = particle.properties['area']['units']
        p_group.attrs["Equivalent circular diameter"] = particle.properties['equivalent circular diameter']['value']
        p_group.attrs["Equivalent circular diameter units"] = particle.properties['equivalent circular diameter']['units']
        p_group.attrs["X"] = particle.properties['x']['value']
        p_group.attrs["X units"] = particle.properties['x']['units']
        p_group.attrs["Y"] = particle.properties['y']['value']
        p_group.attrs["Y units"] = particle.properties['y']['units']
        p_group.attrs["Equivalent circular diameter"] = particle.properties['equivalent circular diameter']['units']
        p_group.attrs["Major axis length"] = particle.properties['major axis length']['value']
        p_group.attrs["Major axis length units"] = particle.properties['major axis length']['units']
        p_group.attrs["Minor axis length"] = particle.properties['minor axis length']['value']
        p_group.attrs["Minor axis length units"] = particle.properties['minor axis length']['units']
        p_group.attrs["Circularity"] = particle.properties['circularity']['value']
        p_group.attrs["Eccentricity"] = particle.properties['eccentricity']['value']
        p_group.attrs["Solidity"] = particle.properties['solidity']['value']
        p_group.attrs["Intensity"] = particle.properties['intensity']['value']
        p_group.attrs["Intensity_max"] = particle.properties['intensity_max']['value']
        p_group.attrs["Intensity_std"] = particle.properties['intensity_std']['value']        
        p_group.create_dataset("Mask",data=particle.mask)
        
        if hasattr(particle, 'image'):
            p_group.create_dataset("Image",data=particle.image.data)
        
    f.close()
In [34]:
save_plist(particles, r'C:\Users\eha56862\Documents\TEM for NPLs-YH-MD\T150\im19.h5')

3. Loading all the particles for each case

In [6]:
os.chdir(t75_path)
t75_h5_files = []
for file in os.listdir(t75_path):
    if file.endswith('h5'):
        t75_h5_files.append(file)
os.chdir(t150_path)
t150_h5_files = []
for file in os.listdir(t150_path):
    if file.endswith('h5'):
        t150_h5_files.append(file)
os.chdir(t200_path)
t200_h5_files = []
for file in os.listdir(t200_path):
    if file.endswith('h5'):
        t200_h5_files.append(file)
In [7]:
t200_h5_files
Out[7]:
['im22.h5', 'im23.h5', 'im24.h5', 'im26.h5', 'im27.h5', 'im28.h5', 'im30.h5']
In [8]:
import h5py
from ParticleSpy.ptcl_class import Particle, Particle_list
import hyperspy as hs
import numpy as np

def load_plist(filename):
    f = h5py.File(filename,'r')
    p_list = Particle_list()
    
    for p_name in list(f.keys()):
        if p_name[:8] == 'Particle':
            p_group = f[p_name]
            particle = Particle()
            
            particle.set_area(p_group.attrs['Area'],p_group.attrs['Area units'])
            particle.set_circularity(p_group.attrs["Circularity"])
            particle.set_circdiam(p_group.attrs["Equivalent circular diameter"],p_group.attrs["Equivalent circular diameter units"])
            particle.set_axes_lengths([p_group.attrs["Major axis length"],p_group.attrs["Minor axis length"]],p_group.attrs["Major axis length units"])
            particle.set_eccentricity(p_group.attrs["Eccentricity"])
            particle.set_intensity(p_group.attrs["Intensity"])            
            particle.set_mask(np.array(p_group['Mask'][:]))
            
            if "Image" in p_group:
                particle.store_im(hs.signals.Signal2D(np.array(p_group['Image'][:])))
                
            p_list.append(particle)
    
    f.close()
    return(p_list)
In [9]:
os.chdir(t75_path)
t75_particles = []
for file in t75_h5_files:
    data = load_plist(file)
    t75_particles.append(data)
os.chdir(t150_path)
t150_particles = []
for file in t150_h5_files:
    data = load_plist(file)
    t150_particles.append(data)
os.chdir(t200_path)
t200_particles = []
for file in t200_h5_files:
    data = load_plist(file)
    t200_particles.append(data)
In [10]:
t75_data_area = []
t75_data_circularity = []
for i, image in enumerate(t75_particles):
    for particle in t75_particles[i].list:
        t75_data_area.append(particle.properties['area']['value'])
        t75_data_circularity.append(particle.properties['circularity']['value'])
t150_data_area = []
t150_data_circularity = []
for i, image in enumerate(t150_particles):
    for particle in t150_particles[i].list:
        t150_data_area.append(particle.properties['area']['value'])
        t150_data_circularity.append(particle.properties['circularity']['value'])
t200_data_area = []
t200_data_circularity = []
for i, image in enumerate(t200_particles):
    for particle in t200_particles[i].list:
        t200_data_area.append(particle.properties['area']['value'])
        t200_data_circularity.append(particle.properties['circularity']['value'])
In [11]:
print(len(t75_data_area), len(t150_data_area), len(t200_data_area))
1524 272 2635
In [12]:
data_area = [t75_data_area, t150_data_area, t200_data_area]
data_circularity = [t75_data_circularity, t150_data_circularity, t200_data_circularity]

4. Plottig the results

In [13]:
import matplotlib.pyplot as plt
In [15]:
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(11,8))
data_names = ['75 C', '150 C', '200 C']
axes.hist(data_area, bins=20, range=(0, 200), density=True, rwidth=0.9, label=data_names)
axes.legend(prop={'size':20})
plt.xlabel('Area $nm^2$', fontsize=20)
plt.ylabel('Probability density', fontsize=20)
Out[15]:
Text(0, 0.5, 'Probability density')
In [16]:
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(11,8))
data_names = ['75 C', '150 C', '200 C']
axes.hist(data_circularity, bins=20, density=True, rwidth=0.9, label=data_names)
axes.legend(prop={'size':20})
plt.xlabel('Circularity', fontsize=20)
plt.ylabel('Probability density', fontsize=20)
Out[16]:
Text(0, 0.5, 'Probability density')
In [17]:
def circularity(particle_area , particle_perimeter):
    
     return (4*np.pi*particle_area)/(particle_perimeter**2)
r = 1
print('Circularity of a perfect circle:', circularity(np.pi * (r**2), 2*np.pi*r))
print('Circularity of a perfect square:', circularity((r**2), 4*r))
Circularity of a perfect circle: 1.0
Circularity of a perfect square: 0.7853981633974483